<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>聊聊定位</title>
    <link rel="stylesheet" type="text/css" href="css/index.css">
</head>

<body id="pagetop">
    <h1>聊聊定位position和尺寸sizing</h1>
    <h2>概述</h2>
    <p>按照盒子模型，HTML一切皆盒子。盒子在文档流里面，或者按行排，或者按列排。</p>
    <h2>包含块 containing block</h2>
    <p>盒子的位置和尺寸（marin border padding width height），受到包含块的影响。<br>
        例如，我们指定盒子的top和left属性来定位，这个top和left就是相对于包含块的。<br>
        再例如，我们设置盒子的宽度和高度为70%，这个百分比也是相对于包含块高度和宽度的百分比的。
    </p>
    <ul>
        <li>包含块是个逻辑上的矩形，不是一个盒子</li>
        <li>包含块通常由一个元素的盒子得到</li>
        <li><em>以包含块为基准定义尺寸和位置的元素，不受包含块的限制，可以溢出包含块限定的区域</em></li>
    </ul>
    <h3>初始包含块 initial containing block</h3>
    <p>我们的网页，根节点是html，它是一个盒子，这个最根上的盒子对应的包含块，就是初始包含块。
        它的大小是浏览器视口（viewport），也就是浏览器工作区的大小。
    </p>
    <h3 id="containingbox">包含块的确定</h3>
    <p>那么，除html元素外，其他元素的包含块如何确定呢？</p>
    <img src=image/box-model.png style="display: block; margin: auto; width: 70%;">
    <ul>
        <li>如果当前元素的position属性（不脱离文档流）为static、relative、或者sticky，
            那么该元素的包含块就是其父元素的内容盒，如上图所示。
        </li>
        <li>如果当前元素的position属性为absolute，其包含块由离它最近的一个position值为非static的祖先的padding盒确定。
            也就是说，它会父节点开始网上找祖先节点，遇到的第一个position值为：relative、absolute、fixed或sticky的节点，
            该节点的padding盒就是包含盒。实际的显示效果为，绝对定位的节点会贴着padding box排，
            参见下面的例子。
        </li>
        <div style="padding:2em;position: relative;border:1px solid brown;width:70%;">
            <p>正常内容，贴着content box排。</p>
            <p style="margin: 0; position: absolute;top:0%;left: 0%;">绝对定位内容，贴着padding box排。</p>
        </div>
        <li>如果positoin为fixed，包含盒就是视口（连续媒体），或者页边界（页媒体）。
            实际的显示效果就是元素固定在浏览器的指定位置,参见本页面的返回页首效果。
        </li>
        <!--1vh 是视口的1%，1vw是视口的1%高度-->
        <a style="position: fixed; bottom:2vh;right: 2vw;background-color: burlywood;"
            href="#pagetop">返回页首</a>
        <li>如果position是absolute或者fixed，最近的祖先节点如果设置了如下属性，那么该元素祖先节点的padding box，
            构成该元素的包含块。
            <ul>
                <li>transform或perspective值不为none</li>
                <li>willchange属性值为transform或者perspective</li>
                <li>filter属性值不是none，或者will-change属性值为filter</li>
                <li>contain属性值为paint</li>
            </ul>
        </li>
    </ul>

    <em>简单点说，在文档流里面的元素，包含块是父元素的内容盒；绝对定位包含块是最近非static祖先的padding盒，
        固定定位元素包含块是视口。
    </em>
    <h3>FC和BFC</h3>
    <p>如前所述，元素的包含块确定了，我们就可以相对于包含块绘制元素了，这个绘制的环境，就是FC format context。</p>
    <p>格式化上下文按照特定的规则，布局它包含的元素。
        例如：块格式上下文（BFC: block format context）将根据块布局规则布局子元素，
        灵活格式上下文 flex formatting context 将其子元素布局为灵活项flex items等。
        每个格式上下文在其上下文中都有特定的布局规则。</p>

    <p>html元素是html文档的根元素，浏览器会为它创建一个BFC，这个BFC又叫<em>初始块格式化上下文 initial block format context</em>。
        这个上下文完成的元素布局，就是我们的<em>常规文档流 normal flow</em>，也叫做<em>文档流</em>。
    </p>
    <p>文档流是用初始块格式化上下文布局的，基本就是块元素竖着排，行元素横着排，如果排不下，就自动换行，但不产生换行符；
        然后块元素如果不做特别指定，宽度默认就是包含块的宽度，高度随元素里面的实际内容增加而变高。
    </p>
    <p>文档流是浏览器的默认布局，如果你没有任何css控制布局页面布局的话，文档流显示内容的顺序和html源代码的内容顺序是一致的。</p>
    <h3>脱离文档流</h3>
    <p>如何才能脱离文档流呢？</p>
    <p>所有元素都在文档流里，除了：</p>
    <ul>
        <li>根元素（html元素）</li>
        <li><em>float元素</em></li>
        <li><em>position为absolute和fixed的元素</em></li>
    </ul>
    <p>这些流外元素会创建一个新的BFC，每个BFC都自己布局。根元素包含了所有的元素，它创建了初始块上下文，所以它没在文档流里。</p>
    <p>创建了自己BFC的元素将：</p>
    <ul>
        <li>包含它内部的浮动（相当于清除浮动）</li>
        <li>排除外部浮动：其盒子不会与外部（非后代）的浮动盒子重叠</li>
        <li>忽略外边界塌缩：塌缩只有在一个BFC里面的元素才会发生作用</li>
    </ul>
    <p>还有一些其他情况也会创建BFC：</p>
    <ul>
        <li>display:inline-block</li>
        <li>display:table-cell</li>
        <li>display:table-caption</li>
        <li>display: table, table-row, table-row-group, table-header-group, table-footer-group</li>
        <li><em>overflow不为visible和clip的元素</em></li>
        <li>contain: layout, content, or paint</li>
        <li>display为 flex 或 inline-grid 的直接后代（儿子），如果它不是flex、grid或table</li>
        <li>display为 grid 或 inline-grid 的直接后代（儿子），如果它不是flex、grid或table</li>
        <li>column-count 或者 column-width 不是auto</li>
        <li>column-span 无论任何值</li>
    </ul>
    <h2>定位 position</h2>
    <p>在文档流里面的元素，顺着往下排，自动定位。但是，有时你想要将元素放到特定位置，
        例如：始终放在视口，也就是浏览器工作区的底端，即使滚动浏览器视口，它也不动。
        或者直接将它放到其容器的top:100px，left:100px处。此时我们可以使用position来完成。
    </p>
    <p>定位的类型有：</p>
    <ul>
        <li>静态定位 static</li>
        <li>相对定位 relative</li>
        <li>绝对定位 absolute</li>
        <li>固定定位 fixed</li>
        <li>吸附定位 sticky</li>
    </ul>
    <h2>1 静态定位 static</h2>
    <p>默认的定位方式就是static，因此你不需要设置。它就是说，元素在文档流里，让浏览器自动定位。</p>
    <p>你要写一篇作文，引用一句古诗：“白日依山尽，黄河入海流”。请问，它的位置在哪里？嗯，文章还没写，
        不知道。但是你写文章时，写到那里，再写这句诗，它就自然在那里了，这，就是静态定位。说白了，就是不显式定位，
        让浏览器去自动定位。
    </p>
    <p>static定位的特点</p>
    <ul>
        <li>不产生bfc</li>
        <li>diaplay属性为inline和inline-block的元素按行排，每行宽度等于容器宽度，排不下自动换行，且不产生换行符</li>
        <li>display属性为block的元素按列排，如果不指定宽度，默认宽度占满容器宽度，如果不指定高度，默认高度随内容增长而自动增长</li>
    </ul>
    <h2>2 relative相对定位</h2>
    <p>要理解相对定位，一个最经典的例子，就是练对列了。参加训练，练队列时，学员排成一排。教练喊：“张三，向前三步走”。
        张三闻讯，向前走了三步，出列了，但是，他原来所占的位置，并没有被别的学员占据，也就是说，张三还在队列中，只是，
        相对于他原来的位置，偏移了一个位置。
    </p>
    <p>同理，相对定位元素不脱离文档流，它先在文档流里面，该咋排咋排，排完后，再按照指定的偏移值，相对于它自己在文档流里面的原位置，
        进行偏移。原位置留空。
    </p>
    relative特点：
    <ul>
        <li>不脱离文档流</li>
        <li>不产生bfc</li>
        <li>保留原位置</li>
        <li>相对于原位置偏移</li>
    </ul>
    <p>示例如下：</p>
    <div style="width: 6em; margin: auto; border: 5px solid lightgrey;padding:0 2em 0em 2em;">
        <p>白日依山尽，</p>
        <p>黄河入海流。</p>
        <p>欲穷千里目，</p>
        <p>更<span style="position:relative;top:-1em;">上</span>一层楼。</p>
    </div>
    <p>上例中，“上”字设置为：style="<em>position:relative; top:-1em;</em>"，于是“上”字相对于自己原来的位置上移，
        且原位置保留。</p>
    <p>你可能发现，这种偏移，似乎在实际的页面设计中用处不大。因为原位置留白了。那么，relative到底一般怎么用呢？
        或者说它的实际用途主要是什么？
        我们通常设置一个元素为relative，但是并不偏移它，因为设定了它为relative，就相当于定义了一个局部坐标系，
        然后它的后代（下级节点）使用absolute定位方式，就可以相对它进行定位。所以，<em>relative元素常用作定位原点</em>。
    </p>
    <h2>3 absolute绝对定位</h2>
    <p>元素脱离文档流，在文档流中没位置，创建BFC，其位置相对于其最近的，position属性为非static的祖先。
        也就是说其包含块是上述祖先的padding盒。参见<a href="#containingbox">包含块的确定</a></p>
    <p>下面的例子，两个嵌套div，外面容器div的position为relative，里面的div的position为absolute，
        位置为距离容器div padding盒 下右1em</p>
    <div style="position: relative; width: 20em; height: 10em; border: 1px solid brown;left:calc(50% - 10em);">
        <div style="position: absolute; bottom: 1em; right: 1em;">
            position:absolute
        </div>
    </div>
    <h2>4 固定定位 fixed</h2>
    <p>固定定位脱离文档流，创建BFC，在文档流中没位置，包含块是视口，因此相对于视口定位。参见本页面的“返回首页”。</p>
    <h2>5 吸附定位 sticky</h2>
    <p>不脱离文档流，如果能在文档流里定位就在文档流里正常定位，当(滚动)抵达设定偏移值（由top、right、bottom、left）时，
        就按照设定偏移值，相对于最近的可滚动祖先元素进行偏移，此时，相当于相对于最近可滚动祖先固定定位。
    </p>
    <div style="overflow-y: scroll; width: 20em;height: 200px;border: 1px solid brown;margin: auto;">
        <p></p>
        <p style="top:5px; position:sticky;width: 100%;color:cornsilk; background-color: brown;">A</p>
        <p>absolute ['æbsəlu:t] 绝对的，完全的</p>
        <p>active ['æktiv] 活动的，激活的，&lt;a&gt;标记的一个伪类</p>
        <p>align [ə'lain] 对齐</p>
        <p>alpha ['ælfə] 透明度，半透明</p>
        <p>anchor ['æŋkə] 锚记&lt;a&gt;标记是这个单词的缩写</p>
        <p>arrow ['ærəu] 箭头</p>
        <p>auto ['ɔ:təu] 自动的</p>
        <p style="top:5px; position:sticky;width: 100%;color:cornsilk; background-color: brown;">B</p>
        <p>background ['bækgraund] 背景</p>
        <p>banner ['bænə] 网幅广告, 旗帜广告, 横幅广告 (网络广告的主要形式, 一般使用GIF格式的图像文件, 可以使用静态图形, 也可用多帧图像拼接为动画图像)</p>
        <p>black [blæk] 黑色</p>
        <p>blink： [bliŋk] 闪亮,闪烁</p>
        <p>block [blɔk] 块</p>
        <p>blue [blu:] 蓝色</p>
        <p>body ['bɔdi] 主体，一个HTML标记</p>
        <p>bold [bəuld] 加粗</p>
        <p>border ['bɔ:də] 边框、框线 边框</p>
        <p>both  [bəuθ] 两者(都);两个(都);是clear属性的一个属性值</p>
        <p>bottom ['bɔtəm] 底;底部，是一个CSS属性</p>
        <p>box [bɔks] 箱;盒;匣</p>
        <p>br 换行标记</p>
        <p>bug [bʌg] 程序设计上的错误，漏洞等</p>
        <p>building ['bildiŋ] 建筑</p>
        <p>button ['bʌtn] 按钮</p>
        <p style="top:5px;position:sticky;width: 100%;color:cornsilk; background-color: brown;">C</p>
        <p>cell [sel] 表格中的单元格</p>
        <p>center ['sentə] 居中</p>
        <p>centimeter ['senti,mi:tə] 厘米</p>
        <p>child [tʃaild] 孩子</p>
        <p>circle ['sə:kl] 圆圈</p>
        <p>class [klɑ:s] 类别</p>
        <p>clear [kliə] 清除</p>
        <p>cm 厘米</p>
        <p>color ['kʌlə] 颜色 </p>
        <p>connected [kə'nektid] 连结的</p>
        <p>contact ['kɔntækt] 联系</p>
        <p>content [kən'tent] 内容</p>
        <p>crosshair 十字准线</p>
        <p>css 层叠样式表</p>
        <p>cursor ['kə:sə] 鼠标指针</p>
        <p style="top:5px;position:sticky;width: 100%;color:cornsilk; background-color: brown;">D</p>
        <p>dashed [dæʃt] 虚线CSS边框常用的一种</p>
        <p>decimal ['desiməl] 十进制 </p>
        <p>decoration [,dekə'reiʃən] 装饰</p>
        <p>default [di'fɔ:lt] 默认的</p>
        <p>definition [,defi'niʃən] 定义 </p>
        <p>design [di'zain] 设计</p>
        <p>display [di'splei ] 显示，CSS的一个属性</p>
        <p>division [di'viʒən] 分区，div就是这个单词的缩写</p>
        <p>document ['dɔkjumənt] 文件文档</p>
        <p>dotted ['dɔtid] 点线</p>
        <p>double ['dʌbl] 双线 </p>
        <p style="top:5px;position:sticky;width: 100%;color:cornsilk; background-color: brown;">E</p>
        <p>element ['elimənt] 元素</p>
        <p style="top:5px;position:sticky;width: 100%;color:cornsilk; background-color: brown;">F</p>
        <p>father ['fɑ:ðə] 父亲,父</p>
        <p>filter ['filtə] 过滤层；滤器</p>
        <p>first [fə:st] 第一个</p>
        <p>fixed [fikst] 固定的，不变的</p>
        <p>float [fləut] 浮动</p>
        <p>font [fɔnt] 字体</p>
        <p>for 在循环语句中的一个保留字</p>
        <p>four 4个</p>
        <p style="top:5px;position:sticky;width: 100%;color:cornsilk; background-color: brown;">G</p>
        <p>gif 一种图像格式</p>
        <p>gray [grei] 灰色</p>
        <p>green [gri:n] 绿色</p>
        <p style="top:5px;position:sticky;width: 100%;color:cornsilk; background-color: brown;">H</p>
        <p>hack [hæk] 常用于CSS中的一些招数，或者类似于偏方的技巧</p>
        <p>hand [hænd] 手</p>
        <p>head [hed] 头部</p>
        <p>height [hait] 高度</p>
        <p>help [help] 帮助</p>
        <p>here [hiə] 这里</p>
        <p>hidden ['hidn] 被隐藏</p>
        <p>home [həum] 首页</p>
        <p>horizontal [,hɔri'zɔntl] 水平的</p>
        <p>hover ['hʌvə] 鼠标指针经过或称为悬浮状态 </p>
        <p style="top:5px;position:sticky;width: 100%;color:cornsilk; background-color: brown;">I</p>
        <p>image ['imidʒ] 图像</p>
        <p>important [im'pɔ:tənt] 重要的</p>
        <p>indent [in'dent] 缩进</p>
        <p>index ['indeks] 索引</p>
        <p>inline 行内</p>
        <p>inner 内部的</p>
        <p>italic [i'tælik] 意大利体，斜体</p>
        <p style="top:5px;position:sticky;width: 100%;color:cornsilk; background-color: brown;">J</p>
        <p>jpg 一种图像格式</p>
        <p>justify ['dʒʌstifai] 两端对齐</p>
        <p style="top:5px;position:sticky;width: 100%;color:cornsilk; background-color: brown;">L</p>
        <p>language ['læŋgwidʒ] 语言 </p>
        <p>last [lɑ:st] 最后一个</p>
        <p>left [left] 左边</p>
        <p>length [leŋθ] 长度</p>
        <p>level ['levl] 级别，例如block-level就是块级</p>
        <p>line [lain] 线</p>
        <p>link [liŋk] 链接</p>
        <p>list [list] 列表</p>
        <p>lowercase ['ləuə,keis] 小写 </p>
        <p style="top:5px;position:sticky;width: 100%;color:cornsilk; background-color: brown;">M</p>
        <p>margin ['mɑ:dʒin] 外边距</p>
        <p>max 最大的</p>
        <p>medium ['mi:diəm] 中间</p>
        <p>menu ['menju:] 菜单</p>
        <p>middle ['midl] 中间</p>
        <p>millimeter ['mili,mi:tə] 毫米</p>
        <p>min 最小的</p>
        <p>model ['mɔdl] 模型 </p>
        <p>move [mu:v] 移动 </p>
        <p style="top:5px;position:sticky;width: 100%;color:cornsilk; background-color: brown;">N</p>
        <p>navigation [,nævi'geiʃən] 导航 </p>
        <p>new [nju:] 新的 </p>
        <p>none [nʌn] 无，没有</p>
        <p>normal ['nɔ:məl] 标准 </p>
        <p style="top:5px;position:sticky;width: 100%;color:cornsilk; background-color: brown;">O</p>
        <p>object ['ɔbdʒikt] 对象 </p>
        <p>oblique [əb'li:k] 一种斜体 </p>
        <p>one 一个 </p>
        <p>only ['əunli] 仅仅</p>
        <p>open ['əupən] 打开 </p>
        <p>optional ['ɔpʃənəl] 可选的 </p>
        <p>orange ['ɔ:rindʒ] 橙色 </p>
        <p>outer ['autə] 外面的 </p>
        <p>overflow [,əuvə'fləu] 溢出 </p>
        <p style="top:5px;position:sticky;width: 100%;color:cornsilk; background-color: brown;">P</p>
        <p>padding ['pædiŋ] 内边距</p>
        <p>point [pɔint] 点 </p>
        <p>pointer ['pɔintə] 指针，指示器 </p>
        <p>position [pə'ziʃən] 定位，位置 </p>
        <p>progress ['prəugres] 进度 </p>
        <p>public ['pʌblik] 公开的 </p>
        <p>purple ['pə:pl] 紫色 </p>
        <p style="top:5px;position:sticky;width: 100%;color:cornsilk; background-color: brown;">R</p>
        <p>red [red] 红色 </p>
        <p>relative ['relətiv] 相对的</p>
        <p>repeat [ri'pi:t] 重复，平铺</p>
        <p>replacement [ri'pleismənt] 替换</p>
        <p>resize 重新设置大小</p>
        <p>right [rait] 右边</p>
        <p>row [rəu] 行</p>
        <p style="top:5px;position:sticky;width: 100%;color:cornsilk; background-color: brown;">S</p>
        <p>scroll [skrəul] 滚动</p>
        <p>shadow ['ʃædəu] 阴影</p>
        <p>silver ['silvə] 银色</p>
        <p>size [saiz] 尺寸</p>
        <p>solid ['sɔlid] 固体，实线 </p>
        <p>solution [sə'lu:ʃən] 方案 </p>
        <p>son [sʌn] 儿子 </p>
        <p>span [spæn] 一个HTML标记 </p>
        <p>special ['speʃəl] 特殊的 </p>
        <p>square [skwɛə] 方块 </p>
        <p>static ['stætik] 静态的 </p>
        <p>strong [strɔŋ] 强壮，加粗的 </p>
        <p>style [stail] 样式 </p>
        <p style="top:5px;position:sticky;width: 100%;color:cornsilk; background-color: brown;">T</p>
        <p>table ['teibl] 表格 </p>
        <p>td 单元格的HTML标记 </p>
        <p>text [tekst] 文本 </p>
        <p>thick [θik] 粗的 </p>
        <p>thin [θin] 细的 </p>
        <p>three [θi:] 三个 </p>
        <p>through [θru:] 穿过 </p>
        <p>title ['taitl] 标题</p>
        <p>top [tɔp] 顶部 </p>
        <p>tr 表格中“行”的HTML标记</p>
        <p>transitional [træn'ziʃənəl] 过渡的 </p>
        <p>two 两个 </p>
        <p>type [taip] 类型 </p>
        <p style="top:5px;position:sticky;width: 100%;color:cornsilk; background-color: brown;">U</p>
        <p>underline [,ʌndə'lain] 下划线 </p>
        <p>upper ['ʌpə] 上面的 </p>
        <p>uppercase ['ʌpə,keis] 大写 </p>
        <p>url 网址 </p>
        <p style="top:5px;position:sticky;width: 100%;color:cornsilk; background-color: brown;">v</p>
        <p>vertical ['və:tikəl] 竖直的 </p>
        <p>visited ['vizit] 访问过的 </p>
        <p style="top:5px;position:sticky;width: 100%;color:cornsilk; background-color: brown;">w</p>
        <p>while [hwail] 白色的 </p>
        <p>width [widθ] 宽度 </p>
        <p style="top:5px;position:sticky;width: 100%;color:cornsilk; background-color: brown;">Y</p>
        <p>yellow ['jeləu] 黄色</p>
        <p></p>
    </div>
    <h2>参考文献</h2>
    <ul>
        <li><a
                href="https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block">https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block</a>
        </li>
        <li><a
                href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Flow_Layout/Intro_to_formatting_contexts">https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Flow_Layout/Intro_to_formatting_contexts</a>
        </li>
        <li><a
                href="https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Introduction">https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Introduction</a>
        </li>
        <li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/position">https://developer.mozilla.org/en-US/docs/Web/CSS/position</a></li>
    </ul>
</body>

</html>